# author: LiuShihao
# data: 2020/11/26 9:14 上午
# youknow: 各位老铁,我的这套代码曾经有人出价三个亿我没有卖,如今拿出来和大家分享,不求别的,只求大家免费的小红心帮忙点一点,这里谢过了。
# desc: 字符串的学习
"""
字符串的驻留机制:
仅保存一份相同且不可变字符串的方法，不同的值被存放在字符串的驻留池中，Python的驻留机制对相同的字符串值保留一份拷贝，后续创建相同字符串时，不会开辟新空间，而是把该字符串的地址赋给新创建的变量。
"""
a = 'Python'
b = 'Python'
c = 'Python'
print(a,id(a))
print(b,id(b))
print(c,id(c))
"""
驻留机制的几种情况：  交互式
  1.字符串的长度为0或者1时
  2.符合标识符（字符、数字、下划线）的字符串
  3.字符串只在编译时驻留，而非运行时
  4.[-5,256]之间的整数数字
"""
# 字符串的长度为0或者1时
a = ''
b = ''
print(a == b)
print(a is b)
a = '1'
b = '1'
print(a == b)
print(a is b)
a = 'abc%'
b = 'abc%'
print(a == b)
print(a is b)
a = 'abc'
b = 'ab'+'c'
c = ''.join(['ab','c'])
print(a,id(a))  # abc 4357320632
print(b,id(b))  # abc 4357320632
print(c,id(c))  # abc 4357630192

a = -5
b = -5
print(a is b)
a = -6
b = -6
print(a is b)
"""
sys中的intern方法强制将两个字符串指向同一个对象
import sys
a = 'abc%'
b = 'abc%'
a is b
False
a = sys.intern(b)
a is b
True
"""
# Pycharm中对字符串进行优化
"""
字符串查询操作：
  1.index   查找子串第一次出现的位置    如果没有 抛出异常
  2.find    查找子串第一次出现的位置    如果没有 返回-1
  3.rindex  查找子串最后一次出现的位置   如果没有 抛出异常
  4.rfind   查找子串最后一次出现的位置   如果没有 返回-1
"""
s = 'hello,hello'
print(s.index('lo'))
print(s.find('lo'))
print(s.rfind('lo'))
print(s.rindex('lo'))
# print(s.index('loo'))   # 如果没有 抛出异常
print(s.find('loo'))      # 如果没有 返回-1
"""
字符串大小写转换
 1.转成大写                 upper
 2.转成小写                 lower
 3.大转小，小转大              swapcase
 4.把第一个字符转换成大写，其余小写         capitalize
 5.把每个单词的第一个字符转换成大写，把每个单词的剩余字符转成小写   title
"""
s = 'hello'
print(s.upper())  # HELLO
s = 'HELLO'
print(s.lower())  # hello
s = 'helloWORLD'
print(s.swapcase()) # HELLOworld
print(s.capitalize()) # Helloworld
s = 'hello WORLD'
print(s.title())  # Hello World
"""
字符串的对齐操作
    1.center 居中对齐   第二个参数默认为空格
    2.ljust  左对齐    第二个参数默认为空格
    3.rjust  右对齐    第二个参数默认为空格
    4.zfill  右对齐   左边用0对齐,该方法只接收一个参数，用于指定字符串的宽度，如果指定宽度小于字符传本身，则返回该字符串
"""
s = 'Hello,Python'
print(s.center(20,"*"))   # ****Hello,Python****
print(s.center(20))         #     Hello,Python
print(s.ljust(20,"*"))      # Hello,Python********
print(s.rjust(20,"*"))      # ********Hello,Python
print(s.zfill(20))          # 00000000Hello,Python
"""
字符串的分割
    1.split  从字符串左边开始分割 默认是空格 返回的值都是列表 通过参数sep指定分割符，通过maxsplit指定最大分割次数，经过最大分割次数后，剩余的子串会单独作为一部分
    2.rsplit 从右边开始分割
"""
s = "hello Python hello"
print(s)
print(s.split()) # 默认分割符是空格   返回的结果是列表  ['hello', 'Python', 'hello']
s = "hello,Python,hello"
print(s)
print(s.split(','))  #以逗号作为分隔符   ['hello', 'Python', 'hello']
print(s.split(sep=',',maxsplit=1))
"""
判断字符串操作的方法：
    1.判断指定字符串是不是合法的标识符(合法的标识符是：字母、数字。下划线)  isidentifier
    2.判断指定字符串是否全部由空白字符组成（回车、换行、水平制表符）   isspace
    3.判断指定的字符串是否全部字母组成                           isalpha
    4.判断指定字符串是否全部由十进制的数字组成（只能是12319）                     isdecimal
    5.判断指定字符串是否全部由数字组成（包括罗马数字、四）                         isnumeric
    6.判断指定字符串是否全部由字母和数字组成                       isalnum
"""
s  = 'hello,Python'
print("判断'hello,Python'是不是合法的标识符",s.isidentifier())
s = '\n\t\r'
print("判断'\n\t\r'是否全部由空白字符组成",s.isspace())
s = 'asda'
print("'asda'是否全部字母组成",s.isalpha())
s = '123'
print("'123'是否全部由数字组成",s.isalnum())
print("'123'是否全部由十进制的数字组成",s.isdecimal())
s = '123四'
print("'123四'是否全部由十进制的数字组成",s.isdecimal())
print("'123四'是否全部由数字组成",s.isnumeric())
s = 'asda121'
print("'asda121'是否全部字母组成",s.isalpha())
print("'asda121'是否全部由数字组成",s.isnumeric())
print("'asda121'是否全部由字母和数字组成",s.isalnum())
print("'asda121'是否全部由数字组成",''.isnumeric())
# 字符串替换   replace  第一个参数：原字符串中的子串     第二个参数：要替换成的子串   第三个参数：指定最大替换次数
s = 'HelloWorld'
print(s)
print(s.replace('World','Python'))
s = 'Hello,Java,Java,Java'
print(s.replace('Java','Python',2))
# 字符串 的合并 join   将元组或列表中的字符串合并成一个字符串
lst = ['hello','Java','Python']
print('|'.join(lst),type('|'.join(lst)))  # hello|Java|Python  <class 'str'>
print(''.join(lst),type(''.join(lst)))   # helloJavaPython     <class 'str'>
"""
字符串的比较
运算符：>、>=、<、<=、=、==、!=
比较规则：
首先比较两个字符串中的第一个字符，如果相等则会继续比较下一个字符，依次比较下去，知道两个字符串中的字符不相等时，其比较的结果就是来哥哥字符串的比较结果，两个字符串中的所有后续字符将不再被比较。
比较原理：
两个字符串进行比较时，比较的是其ordinal value（原始值），调用内置函数ord可以得到指定字符的ordinal value。与内置函数对应的是内置函数chr，调用内置函数chr时指定ordinal value可以得到其对应的字符。
"""
print('apple'>'app')        # True
print('apple'>'banana')    # False
print(ord('a'),ord('b'))   # 97 98
print(chr(97),chr(98))      #a b
'''
==与is的区别
==比较的是value
is比较的是id是否相等
'''
a = b = 'Python'
c = 'Python'
print(a == b)
print(a == c)
print(a is b)
print(a is c)
# 即 a，b，c 在内存空间中指向的是同一个对象
"""
字符串切片操作 [start：stop：step]
s[5:]   如果不指定起始位置 索引将从0开始  ；s[:6]   如果不指定结束位置 索引将到最后
"""
s = 'hello,world'
print(s)                # hello,world
print(s[:5])            # hello  索引从0开始  到5结束 但是不包含索引为5的字符
print(s[6:])            # world  索引从6开始   到最后结束
print(s[1:5:1])         # ello   索引从1开始到5 结束 不包括5  步长为1
print(s[::2])         # el        索引从0开始到最后结束 包括最后一个元素  步长为2
print(s[::-1])         # dlrow,olleh  开始 结束都为默认 ，默认从最后一位字符开始，因为步长为负数

"""
格式化字符串的两种方式：
    1.%做占位符  '我叫%s,今年%i岁了' % (name,age)   str类型占位符：%s  int类型占位符：%i或%d  浮点数类型占位符：%f
    2.{}做占位符 '我叫{0},今年{1}岁了'.format(name,age)
    3.f'我叫{name},今年{age}岁了'
"""
name = '张三'
age = 19
print('我叫%s，今年%i岁了' % (name,age))
print('我叫{0}，今年{1}岁了'.format(name,age))
print(f'我叫{name}，今年{age}岁了')
print('%10d' % 99)  # 10d代表的是字符串的宽度
print('%.3f' % 3.1415926)  # .3f代表保留三位小数
print('%10.3f' % 3.1415926) # 10.3f 同时表示宽度和经度
print('{:.3}'.format(3.1415926))  # 0代表第一个占位符可以省略   .3代表一共保留三位数   3.14
print('{0:.3f}'.format(3.1415926))  # .3f代表的是保留三位小数                 3.142
print('{:10.3f}'.format(3.1415926))  # 10代表宽度   .3f代表保留三位小数
# 字符串的编码与解码
s = '千山鸟飞绝万径人踪灭'
# 编码
print(s.encode(encoding='GBK'))  #GBK简体中文 一个中文占两个字节   b'\xc7\xa7\xc9\xbd\xc4\xf1\xb7\xc9\xbe\xf8\xcd\xf2\xbe\xb6\xc8\xcb\xd7\xd9\xc3\xf0'
print(s.encode(encoding='UTF-8'))#UTF-8简体中文 一个中文占三个字节 b'\xe5\x8d\x83\xe5\xb1\xb1\xe9\xb8\x9f\xe9\xa3\x9e\xe7\xbb\x9d\xe4\xb8\x87\xe5\xbe\x84\xe4\xba\xba\xe8\xb8\xaa\xe7\x81\xad'
# 解码
byte = s.encode(encoding='GBK')
print(type(byte))  # <class 'bytes'>
print(byte.decode(encoding='GBK'))
byte = s.encode(encoding='UTF-8')
print(byte.decode(encoding='UTF-8'))   # 如果解码是的编码格式不对则会抛出异常




